#ifndef __QE_SPI_FLASH_H__
#define __QE_SPI_FLASH_H__


#include "qe_core.h"


/**
 * status register bits
 */
enum {
    QE_SPIFLASH_SR_BUSY = (1 << 0),                  /**< busing */
    QE_SPIFLASH_SR_WEL = (1 << 1),                   /**< write enable latch */
    QE_SPIFLASH_SR_SRP = (1 << 7),                   /**< status register protect */
};

/**
 * flash program(write) data mode
 */
enum flash_write_mode {
    FLASH_WM_PAGE_256B = 1 << 0,                            /**< write 1 to 256 bytes per page */
    FLASH_WM_BYTE = 1 << 1,                                 /**< byte write */
    FLASH_WM_AAI = 1 << 2,                                  /**< auto address increment */
    FLASH_WM_DUAL_BUFFER = 1 << 3,                          /**< dual-buffer write, like AT45DB series */
};
#define FLASH_WM_BYTE_AAI		(FLASH_WM_BYTE | FLASH_WM_AAI)
#define FLASH_WM_BYTE_DBF		(FLASH_WM_BYTE | FLASH_WM_DUAL_BUFFER)

/* flash capacity define */
#define FLASH_CKB(n)			(n * 1024)
#define FLASH_CMB(n)			(n * 1024 * 1024)
#define FLASH_SKB(n)			(n * 1024)

#define QE_SPIFLASH_CMD_PAGE_PROGRAM					0x02
#define QE_SPIFLASH_CMD_READ_DATA						0x03
#define QE_SPIFLASH_CMD_WRITE_DISABLE					0x04
#define QE_SPIFLASH_CMD_READ_SR							0x05
#define QE_SPIFLASH_CMD_WRITE_ENABLE					0x06
#define QE_SPIFLASH_CMD_ENABLE_RESET					0x66
#define QE_SPIFLASH_CMD_RESET							0x99
#define QE_SPIFLASH_CMD_WORD_PROGRAM					0xAD
#define QE_SPIFLASH_CMD_ENTER_4B_ADDRESS_MODE			0xB7
#define QE_SPIFLASH_CMD_ERASE_CHIP						0xC7
#define QE_SPIFLASH_CMD_EXIT_4B_ADDRESS_MODE			0xE9
#define QE_SPIFLASH_CMD_JEDEC_ID						0x9F
							

/* Support manufacturer JEDEC ID */
#define JEDEC_ID_CYPRESS                             0x01
#define JEDEC_ID_FUJITSU                             0x04
#define JEDEC_ID_EON                                 0x1C
#define JEDEC_ID_ATMEL                               0x1F
#define JEDEC_ID_MICRON                              0x20
#define JEDEC_ID_AMIC                                0x37
#define JEDEC_ID_SANYO                               0x62
#define JEDEC_ID_INTEL                               0x89
#define JEDEC_ID_ESMT                                0x8C
#define JEDEC_ID_FUDAN                               0xA1
#define JEDEC_ID_HYUNDAI                             0xAD
#define JEDEC_ID_SST                                 0xBF
#define JEDEC_ID_MACRONIX                            0xC2
#define JEDEC_ID_GIGADEV                          	 0xC8
#define JEDEC_ID_ISSI                                0xD5
#define JEDEC_ID_WINBOND                             0xEF

#define FLASH_F_RESET                                0x01
#define FLASH_F_4BYTE                                0x02

#define SPIFLASH_CTRL_GET_CHIPINFO                   0x21
#define SPIFLASH_CTRL_BLOCK_ERASE                    0x22

/* manufacturer information */
struct spiflash_mf {
    char *name;
    qe_u8 id;
};

struct qe_spiflash_chip {
	char *name;
	qe_u8  mf_id;
	qe_u8  mt_id;
	qe_u8  capacity_id;
	qe_u8  erase_gran_cmd;
	qe_u32 capacity;
	qe_u16 write_mode;
	qe_u8 flag;
    qe_u8 reserve; 
	qe_u32 erase_gran;
};

struct qe_spiflash_erase_msg {
    qe_u32 addr;
    qe_u32 size;
    qe_u32 erase_gran;
    qe_u8 erase_cmd;
    qe_u8 reserve[3]; 
};

struct qe_spiflash_device {

	struct qe_device 		 parent;
	struct qe_spi_device    *spi_device;
	struct qe_spiflash_chip  chip;

	qe_u32 			 nr_sectors;				/* sector number */
	qe_u32				 sector_size;				/* bytes per sector */
	qe_u32     	     block_size;				/* bytes per erase block */

	qe_u32 			 address_4byte:1;
	qe_u32 			 reserve:31;
};
typedef struct qe_spiflash_device *qe_spiflash_t;



qe_size_t qe_spiflash_read(qe_spiflash_t  flash,
							   qe_u32    addr,
							   qe_size_t      size,
							   void          *buffer);

qe_err_t qe_spiflash_write(qe_spiflash_t  flash,
							   qe_u32    addr,
							   qe_size_t      size,
							   const void    *buffer);

qe_err_t qe_spiflash_erase(qe_spiflash_t flash,
								   qe_u32   addr,
								   qe_size_t     size);

qe_err_t qe_spiflash_chip_erase(qe_spiflash_t flash);

qe_spiflash_t qe_spiflash_find(const char *name);
qe_spiflash_t qe_spiflash_probe(const char *flash_dev_name, 
    const char *spi_dev_name, struct qe_spiflash_chip *chipinfo);

#endif /* qe_spiflash_t */

